﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using HYCodeBase.Math;
using HYRevitCode.XYZUtility;

namespace HYRevitCode.CurveUtility
{
	public static class CurveUtilityMethod
	{
		public static Curve GetUnBoundCurve(Curve input)
		{
			if (null == input || !input.IsBound)
			{
				return input;
			}
			Curve curve = input.Clone();
			curve.MakeUnbound();
			return curve;
		}

		public static bool IfPointOnCurve(Curve inputCurve, XYZ inputPoint, bool ifBound = true)
		{
			if (null == inputCurve || inputPoint == null)
			{
				return false;
			}
			Curve curve = inputCurve.Clone();
			if (curve.IsBound)
			{
				curve.MakeUnbound();
			}
			XYZ xyzpoint = inputCurve.Project(inputPoint).XYZPoint;
			XYZ xyzpoint2 = curve.Project(inputPoint).XYZPoint;
			double val = xyzpoint.DistanceTo(inputPoint);
			double val2 = xyzpoint2.DistanceTo(inputPoint);
			double precision = MathUtility.GetPrecision(3);
			return MathUtility.Lessthan_Or_Equal(val, precision) && MathUtility.Lessthan_Or_Equal(val2, precision);
		}

		public static bool IfTwoBoundLineIsSameLine(Line inputOne, Line inputTwo)
		{
			return XYZUtilityMethod.Is_Points_Collinear(inputOne.GetEndPoint(0), inputOne.GetEndPoint(1), inputTwo.GetEndPoint(0), 1E-09) && XYZUtilityMethod.Is_Points_Collinear(inputOne.GetEndPoint(0), inputOne.GetEndPoint(1), inputTwo.GetEndPoint(1), 1E-09);
		}

		public static bool TryGetIntersectionPoint(Curve inputCurveOne, Curve inputCurveTwo, out XYZ interectionPoint)
		{
			interectionPoint = null;
			IntersectionResultArray intersectionResultArray = null;
			bool result;
			try
			{
				if ((int)inputCurveOne.Intersect(inputCurveTwo, out intersectionResultArray) == 8)
				{
					interectionPoint = intersectionResultArray.get_Item(0).XYZPoint;
					result = true;
				}
				else
				{
					result = false;
				}
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		public static List<Curve> SplitOneCurve(Curve inputCurve, double useLength)
		{
			List<Curve> list = new List<Curve>();
			if (!inputCurve.IsBound)
			{
				return list;
			}
			double endParameter = inputCurve.GetEndParameter(0);
			double endParameter2 = inputCurve.GetEndParameter(1);
			double num = 0.0;
			double length = inputCurve.Length;
			num = endParameter;
			double num2 = (endParameter2 - endParameter) * useLength / length;
			while (MathUtility.Lessthan_Or_Equal(num + num2, endParameter2))
			{
				Curve curve = inputCurve.Clone();
				try
				{
					curve.MakeBound(num, num + num2);
					list.Add(curve);
				}
				catch
				{
				}
				num += num2;
			}
			if (MathUtility.Lessthan_Or_Equal(num, endParameter2))
			{
				Curve curve = inputCurve.Clone();
				try
				{
					curve.MakeBound(num, endParameter2);
					list.Add(curve);
				}
				catch
				{
				}
			}
			return list;
		}

		public static Curve TransformCurveAtZAixs(Curve inputCurve, double moveZValue, bool ifAbsolute = true)
		{
			XYZ endPoint = inputCurve.GetEndPoint(0);
			XYZ xyz;
			if (!ifAbsolute)
			{
				xyz = new XYZ(endPoint.X, endPoint.Y, endPoint.Z + moveZValue);
			}
			else
			{
				xyz = new XYZ(endPoint.X, endPoint.Y, moveZValue);
			}
			Transform transform = Transform.CreateTranslation(xyz.Add(-endPoint));
			return inputCurve.Clone().CreateTransformed(transform);
		}

		public static Line AdjustLineToNearPoint(Line input, XYZ inputPoint)
		{
			XYZ endPoint = input.GetEndPoint(0);
			XYZ endPoint2 = input.GetEndPoint(1);
			XYZ xyz = endPoint;
			bool flag = true;
			if (MathUtility.GreaterThan(endPoint2.DistanceTo(inputPoint), endPoint.DistanceTo(inputPoint)))
			{
				xyz = endPoint2;
				flag = false;
			}
			if (flag)
			{
				return Line.CreateBound(xyz, inputPoint);
			}
			return Line.CreateBound(inputPoint, xyz);
		}

		public static Curve CreateOffsetCurve(Curve curve, double dOffsetDist)
		{
			Line line = curve as Line;
			if (line != null)
			{
				XYZ xyz = line.Direction.CrossProduct(XYZ.BasisZ);
				xyz = xyz.Normalize() * dOffsetDist;
				return Line.CreateBound(line.GetEndPoint(0) + xyz, line.GetEndPoint(1) + xyz);
			}
			Arc arc = curve as Arc;
			if (null != arc)
			{
				XYZ center = arc.Center;
				double num = arc.Radius + dOffsetDist;
				XYZ xyz2 = arc.Evaluate(0.5, true);
				XYZ xyz3 = arc.GetEndPoint(0).Add(-center).Normalize();
				XYZ xyz4 = arc.GetEndPoint(1).Add(-center).Normalize();
				XYZ xyz5 = xyz2.Add(-center).Normalize();
				XYZ xyz6 = center.Add(xyz3.Multiply(num));
				XYZ xyz7 = center.Add(xyz4.Multiply(num));
				XYZ xyz8 = center.Add(xyz5.Multiply(num));
				return Arc.Create(xyz6, xyz7, xyz8);
			}
			throw new ArgumentException();
		}

		public static bool LineToString(Line line, out string lineString)
		{
			bool result;
			try
			{
				lineString = "Line:" + line.GetEndPoint(0).ToString() + ":" + line.GetEndPoint(1).ToString();
				result = true;
			}
			catch
			{
				lineString = string.Empty;
				result = false;
			}
			return result;
		}

		public static bool LineToString(List<Line> lstLine, out List<string> lstLineString)
		{
			lstLineString = new List<string>();
			bool result;
			try
			{
				string empty = string.Empty;
				foreach (Line line in lstLine)
				{
					CurveUtilityMethod.LineToString(line, out empty);
					lstLineString.Add(empty);
				}
				result = true;
			}
			catch
			{
				lstLineString = null;
				result = false;
			}
			return result;
		}

		public static double GetBulge(XYZ startPoint, XYZ endStart, XYZ CenterPt, bool isAnticlockwise)
		{
			XYZ xyz = startPoint;
			XYZ xyz2 = endStart;
			if (!isAnticlockwise)
			{
				xyz = endStart;
				xyz2 = startPoint;
			}
			double num = xyz.DistanceTo(CenterPt);
			double num2 = xyz.DistanceTo(xyz2) / 2.0;
			double num3 = num - Math.Sqrt(num * num - num2 * num2);
			double angle = XYZUtilityMethod.GetAngle(CenterPt, xyz);
			double angle2 = XYZUtilityMethod.GetAngle(CenterPt, xyz2);
			double num4 = MathUtility.BetweenTheAngles(angle, angle2, true);
			if (MathUtility.IsEqual(num4, System.Math.PI))
			{
				num3 = num2;
			}
			else if (MathUtility.LessThan(System.Math.PI, num4))
			{
				num3 = num * 2.0 - num3;
			}
			double num5 = num3 / num2;
			if (!isAnticlockwise)
			{
				num5 *= -1.0;
			}
			return num5;
		}

		public static void GetRadiusWithBulge(XYZ startPoint, XYZ endPoint, double dBulge, ref double dRadius)
		{
			if (MathUtility.IsEqual(dBulge, 1.0))
			{
				dRadius = startPoint.DistanceTo(endPoint) / 2.0;
				return;
			}
			double num = startPoint.DistanceTo(endPoint) / 2.0;
			double num2 = Math.Abs(dBulge) * num;
			dRadius = (num * num + num2 * num2) / (num2 * 2.0);
		}

		public static bool IsAntiClockwise(List<XYZ> loop)
		{
			int i = 0;
			int num = 0;
			int num2 = 0;
			while (i < loop.Count)
			{
				XYZ xyz = loop[i];
				XYZ xyz2;
				if (i == 0)
				{
					xyz2 = loop[loop.Count - 1];
				}
				else
				{
					xyz2 = loop[i - 1];
				}
				XYZ xyz3;
				if (i == loop.Count - 1)
				{
					xyz3 = loop[0];
				}
				else
				{
					xyz3 = loop[i + 1];
				}
				if (MathUtility.LessThan((xyz.X - xyz2.X) * (xyz3.Y - xyz.Y) - (xyz.Y - xyz2.Y) * (xyz3.X - xyz.X), 0.0))
				{
					num++;
				}
				else
				{
					num2++;
				}
				i++;
			}
			return num2 > num;
		}

		public static void GetCenterWithBulge(XYZ SP, XYZ EP, double dBulge, ref XYZ ptCenter)
		{
			if (MathUtility.IsEqual(dBulge, 1.0))
			{
				ptCenter = XYZUtilityMethod.CalculatMidPoint(SP, EP);
				return;
			}
			double num = SP.DistanceTo(EP) / 2.0;
			double num2 = Math.Abs(dBulge) * num;
			double num3 = (num * num + num2 * num2) / (num2 * 2.0);
			XYZ xyz = XYZUtilityMethod.CalculatMidPoint(SP, EP);
			XYZ xyz2 = (EP - SP).Normalize();
			if (dBulge > 0.0)
			{
				xyz2 = XYZUtilityMethod.RotateTo(xyz2, System.Math.PI*.5, XYZ.BasisZ);
				xyz2 *= num3 - num2;
				ptCenter = xyz + xyz2;
				return;
			}
			xyz2 = XYZUtilityMethod.RotateTo(xyz2, -System.Math.PI*.5, XYZ.BasisZ);
			xyz2 *= num3 - num2;
			ptCenter = xyz + xyz2;
		}

		public static void GetArcInfoWithBulge(XYZ SP, XYZ EP, double dBulge, ref XYZ ptCenter, ref double dRadius, ref double dSAngle, ref double dEAngle)
		{
			CurveUtilityMethod.GetCenterWithBulge(SP, EP, dBulge, ref ptCenter);
			dRadius = SP.DistanceTo(ptCenter);
			Math.Atan(1.0 / Math.Abs(dBulge));
			if (dBulge > 0.0)
			{
				dSAngle = XYZUtilityMethod.GetAngle(ptCenter, SP);
				dEAngle = XYZUtilityMethod.GetAngle(ptCenter, EP);
				return;
			}
			dSAngle = XYZUtilityMethod.GetAngle(ptCenter, EP);
			dEAngle = XYZUtilityMethod.GetAngle(ptCenter, SP);
		}
	}
}
